package com.cs2340.taskplusplus;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * The TaskList is a Doable object that contains a list of other Doable objects:
 * Essentially it is a list of subtasks, however, those subtasks can ALSO be TaskLists themselves
 * @author GRILLENBANNER
 *
 */
public class TaskList implements Doable
{
	protected ArrayList<Doable> list;
	protected ArrayList<Label> labels;
	protected Date date;
	protected String name, description, tableName, parentTable, labelTable;
	protected Location location;
	protected boolean isDone,isList;
	
	/**
	 * Constructs a TaskList from the database using its name to identify it
	 * @param tableName
	 */
	public TaskList(String tableName)
	{
		this.tableName = tableName;
		this.name = tableName.substring(tableName.lastIndexOf("_")+1);
		this.parentTable = tableName.substring(0,tableName.lastIndexOf("_"));
		
		if (!this.parentTable.contains("_"))
			this.parentTable = null;
		
		this.labels = new ArrayList<Label>();
		this.labelTable = "labels_" + tableName;
		
		TaskListDatabase.buildList(this);
		TaskListDatabase.buildLabels(this);
		if (!name.equals("MasterList"))
		{
			TaskListDatabase.fillInfo(this);
		}
		
		this.isList = true;
	}

	/**
	 * Constructs a TaskList by expanding it from a simple Task
	 * @param parent
	 * @param name
	 */
	public TaskList(String parent, String name)
	{
		this.name = name;
		this.parentTable = parent;
		this.tableName = parentTable + "_"+ name;
		if (!this.parentTable.contains("_"))
			this.parentTable = null;
		list = new ArrayList<Doable>();
		TaskListDatabase.expand(this);
		this.isList = true;		
	}
	
	/**
	 * Construct a TaskList from scratch
	 * @param parent
	 * @param name
	 * @param description
	 */
	public TaskList(String parent, String name, String description, Date due, ArrayList<Label> labels, Location loc)
	{
		this.parentTable = parent;
		this.name = name;
		this.description = description;
		this.list = new ArrayList<Doable>();
		this.location = loc;
		if (due == null)
			this.date = new Date();
		else
			this.date = due;
		
		isList = true;
		isDone = false;
		if (parent == null)
			this.tableName = Account.username + "_MasterList";
		else
		{
			this.tableName = parent + "_"+ name;
			this.labelTable = "labels_" + tableName;
			TaskListDatabase.addToParent(this);
		}
		this.labelTable = "labels_" + tableName;
		
		this.labels = new ArrayList<Label>();
		if (labels != null)
		{
			this.labels = labels;
		}
		
		TaskListDatabase.newTaskList(this);		
	}
	
	public void delete()
	{
		TaskListDatabase.delete(this);
		for (Doable d : list)
		{
			d.delete();
		}
	}
	
	/**
	 * Insert a task into the task list and add it to the database
	 * @param task
	 */
	public void addTask(Doable task)
	{
		list.add(task);
		TaskListDatabase.addTask(this, task);
	}

	public void removeTask(Doable task)
	{
		list.remove(task);
		TaskListDatabase.removeTask(this, task);
		if (task.isList())
		{
			for (Doable d : list)
			{
				d.delete();
			}
		}
	}
	
	/**
	 * gets table name
	 * @return
	 */
	public String getTableName()
	{
		return tableName;
	}
	
	public int getTaskIndex(String name)
	{
		int ind = -1;
		int i = 0;
		for (Doable d : list)
		{			
			if (d.getName().equals(name))
				ind = i;
			i++;
		}
		return ind;
	}

	/**
	 * gets description
	 */
	public String getDescription()
	{
		return description;
	}
	
	/**
	 * Sets description
	 */
	public void setDescription(String desc)
	{
		description = desc;
	}
	
	/**
	 * gets location
	 */
	public Location getLocation()
	{
		return location;
	}
	
	/**
	 * sets location
	 */
	public void setLocation(Location loc)
	{
		location = loc;
	}
	
	public void expand(String taskName)
	{
		Task t = null;
		int i = 0;
		for (Doable d : this.getList())
		{
			if (d.getName().equals(taskName))
			{
				t = (Task) d;
			}
			i++;
		}
		if (t != null)
		{
			TaskList tsk = t.expand();
			this.removeTask(t);
			this.addTask(tsk);
		}
	}
	
	/**
	 * return a list of categories the tasklist belongs to
	 */
	public ArrayList<Label> getLabels()
	{
		return labels;
	}
	
	/**
	 * add a category to the category list
	 */
	public void addLabel(Label l)
	{
		if (!this.hasLabel(l))
		{
			labels.add(l);
			TaskListDatabase.addLabel(this, l);
		}
	}
	
	/**
	 * remove a category from the category list
	 */
	public void removeLabel(Label l)
	{
		if (this.hasLabel(l))
		{
			labels.remove(l);
			TaskListDatabase.removeLabel(this, l);
		}
	}
	
	/**
	 * check off the tasklist
	 */
	public void setDone()
	{
		this.isDone = true;
		TaskListDatabase.setDone(this);
		for (Doable d : list)
		{
			d.setDone();
		}
	}
	
	/**
	 * uncheck the tasklist
	 */
	public void setNotDone()
	{
		isDone = false;
		TaskListDatabase.setNotDone(this);
		for (Doable d : list)
		{
			d.setNotDone();
		}
	}

	/**
	 * gets the tasklist's name
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * sets the name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * is the tasklist checked off?
	 */
	public boolean isDone() {
		return isDone;
	}
	
	/**
	 * get the list of subtasks
	 * @return
	 */
	public ArrayList<Doable> getList(){
		return list;
	}

	/**
	 * get the name of the tasklist's parent
	 */
	public String getParentTable() {
		return parentTable;
	}

	/**
	 * set the name of the tasklist's parent
	 */
	public void setParentTable(String tl) {
		this.parentTable = tl;		
	}

	public void setLabelTable(String labelTable) {
		this.labelTable = labelTable;
	}

	public String getLabelTable() {
		return labelTable;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public Date getDate() {
		return date;
	}

	/**
	 * checks to see if the TaskList has the given label applied.
	 */
	public boolean hasLabel(Label l) {
		return labels.contains(l);
	}

	public boolean isAfter(Date d) {
		return date.after(d);
	}

	public boolean isOn(Date d) {
		return this.date.equals(d);
	}

	public boolean isBefore(Date d) {
		return this.date.before(d);
	}

	public boolean isList() {
		return isList;
	}

	public void setLabels(ArrayList<Label> labels) 
	{
		this.labels = labels;
		TaskListDatabase.newLabels(this);
		for (Label l : labels)
		{
			TaskListDatabase.addLabel(this, l);
		}
	}

	public void setList(ArrayList<Doable> list) 
	{
		this.list = list;
		TaskListDatabase.newList(this);
		for (int i = 0; i < list.size(); i++)
		{
			TaskListDatabase.addTask(this, list.get(i));
		}
	}	
}
